package net.zoneland.knowledge.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.google.common.base.Preconditions;
import net.zoneland.knowledge.exceptions.DjExceptionCode;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;

import net.zoneland.knowledge.dao.SubjectLevelMapper;
import net.zoneland.knowledge.model.EsQuestion;
import net.zoneland.knowledge.model.QaQueryDto;
import net.zoneland.knowledge.model.SubjectLevel;
import net.zoneland.knowledge.model.SubjectLevelExample;
import net.zoneland.knowledge.service.SubjectLevelService;

/**
 * .
 *
 * @author: bcc
 *     2022/7/7
 */
@Service
public class SubjectLevelServiceImpl implements SubjectLevelService {

    /**
     * 顺序计算相乘基数 {@value #ORDER_MULTIPLY_NUMBER}.
     */
    private static final long ORDER_MULTIPLY_NUMBER = 100000000L;

    @Autowired
    private SubjectLevelMapper subjectLevelMapper;

    @Override
    public List<EsQuestion> queryAll(final QaQueryDto qaQueryDto) {
        List<String> categoryList = qaQueryDto.getCategoryList();
        if (CollectionUtils.isEmpty(categoryList) && StringUtils.isNotBlank(qaQueryDto.getCategory())) {
            categoryList = Lists.newArrayList(qaQueryDto.getCategory());
        }
        List<Integer> levels = Lists.newArrayList(1);
        if (qaQueryDto.isFetchLevel2()) {
            levels.add(2);
        }
        final SubjectLevelExample example = new SubjectLevelExample();
        final SubjectLevelExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false).andSubjectLevelIn(levels);
        if (CollectionUtils.isNotEmpty(categoryList)) {
            criteria.andCategoryIn(categoryList);
        }
        example.setOrderByClause(" orders asc");
        List<SubjectLevel> subjectLevels = subjectLevelMapper.selectByExample(example);
        //同时查询二级科目时，排序要求：二级科目显示在归属的一级科目之后。
        // 排序考虑数据分类
        if (qaQueryDto.isFetchLevel2()) {

            final Map<String, List<SubjectLevel>> categoryMap = subjectLevels.stream()
                .collect(Collectors.groupingBy(SubjectLevel::getCategory));
            List<SubjectLevel> rs = new ArrayList<>();
            for (List<SubjectLevel> subjectLevels1 : categoryMap.values()) {
                final Map<String, SubjectLevel> subjectLevelMap = subjectLevels1.stream()
                    .filter(subjectLevel -> 1 == subjectLevel.getSubjectLevel())
                    .collect(Collectors.toMap(SubjectLevel::getId, item -> item));
                subjectLevels1.stream()
                    .forEach(item -> {
                        if (1 == item.getSubjectLevel()) {
                            item.setTmpOrder(ORDER_MULTIPLY_NUMBER * item.getOrders());
                        } else {
                            SubjectLevel parent = subjectLevelMap.get(item.getParentId());
                            if (null != parent) {
                                item.setTmpOrder(ORDER_MULTIPLY_NUMBER * parent.getOrders() + item.getOrders());
                            }
                        }
                    });
                List<SubjectLevel> subjectLevelsAfterSort  = subjectLevels1.stream()
                    .sorted(Comparator.comparing(SubjectLevel::getTmpOrder))
                    .collect(Collectors.toList());
                rs.addAll(subjectLevelsAfterSort);
            }
            return transfer(rs);
        }
        return transfer(subjectLevels);
    }

    @Override
    public List<SubjectLevel> queryByPath(final QaQueryDto qaQueryDto) {
        final SubjectLevelExample example = new SubjectLevelExample();
        final SubjectLevelExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false);
        criteria.andCategoryEqualTo(qaQueryDto.getCategory());
        example.setOrderByClause(" orders asc");
        //查询三级科目
        if (StringUtils.isNotBlank(qaQueryDto.getLevel2Title())) {
            criteria.andParentSubjectNameEqualTo(qaQueryDto.getLevel2Title());
            criteria.andSubjectLevelEqualTo(3);
        } else {
            //查询二级科目
            criteria.andParentSubjectNameEqualTo(qaQueryDto.getLevel1Title());
            criteria.andSubjectLevelEqualTo(2);
        }
        return subjectLevelMapper.selectByExample(example);
    }

    private List<EsQuestion> transfer(final List<SubjectLevel> subjectLevels) {
        return subjectLevels.stream().map(item-> {
            EsQuestion esQuestion = new EsQuestion();
            esQuestion.setCategory(item.getCategory());
            if (1 == item.getSubjectLevel()) {
                esQuestion.setLevel1Title(item.getSubjectName());
            } else {
                esQuestion.setLevel1Title(item.getParentSubjectName());
                esQuestion.setLevel2Title(item.getSubjectName());
            }

            return esQuestion;
        }).collect(Collectors.toList());
    }

    /**
     * 通过层级查询下级科目.
     * @param subjectName 父科目
     * @param category 分类
     * @return
     */
    @Override
    public List<SubjectLevel> queryByLevel(final String subjectName, final String category) {
        Preconditions.checkArgument(StringUtils.isNotBlank(subjectName), DjExceptionCode.DJ_OBJ_NULL);
        Preconditions.checkArgument(StringUtils.isNotBlank(category), DjExceptionCode.DJ_OBJ_NULL);
        return subjectLevelMapper.selectByLevel(category, subjectName);
    }
}
